package model

import (
	myConfig "common/config"
	myconn "common/conn"
	"common/helper"
	myredis "common/redis"
	myUserHelp "common/userHelp"
	"database/sql"
	"errors"
	"fmt"
	"github.com/doug-martin/goqu/v9/exp"
	"member/contrib/validator"
	"strconv"
	"time"

	g "github.com/doug-martin/goqu/v9"
	"github.com/shopspring/decimal"
	"github.com/valyala/fasthttp"
)

// tblWithdraw 出款
type tblWithdraw struct {
	ID           string  `db:"id" json:"id" cbor:"id"`                                  //
	OID          string  `db:"oid" json:"oid" cbor:"oid"`                               //三方订单
	UID          string  `db:"uid" json:"uid" cbor:"uid"`                               //用户ID
	ParentId     string  `db:"parent_id" json:"parent_id" cbor:"parent_id"`             //上级uid
	FID          string  `db:"fid" json:"fid" cbor:"fid"`                               //通道id
	Amount       float64 `db:"amount" json:"amount" cbor:"amount"`                      //金额
	Fee          float64 `db:"fee" json:"fee" cbor:"fee"`                               //手续费
	State        int     `db:"state" json:"state" cbor:"state"`                         //0:待确认:1存款成功2:已取消
	Automatic    int     `db:"automatic" json:"automatic" cbor:"automatic"`             //1:自动转账2:脚本确认3:人工确认
	PixAccount   string  `db:"pix_account" json:"pix_account" cbor:"pix_account"`       //银行名
	RealName     string  `db:"real_name" json:"real_name" cbor:"real_name"`             //持卡人姓名
	PixId        string  `db:"pix_id" json:"pix_id" cbor:"pix_id"`                      //银行卡号
	CreatedAt    int64   `db:"created_at" json:"created_at" cbor:"created_at"`          //
	ConfirmAt    int64   `db:"confirm_at" json:"confirm_at" cbor:"confirm_at"`          //确认时间
	ConfirmUID   string  `db:"confirm_uid" json:"confirm_uid" cbor:"confirm_uid"`       //确认人uid
	ReviewRemark string  `db:"review_remark" json:"review_remark" cbor:"review_remark"` //确认人名
	WithdrawAt   int64   `db:"withdraw_at" json:"withdraw_at" cbor:"withdraw_at"`       //三方场馆ID
}

// paymentWithdrawResp 提款
type paymentWithdrawResp struct {
	OrderID string `json:"order_id" cbor:"order_id"` //我方订单号
	Oid     string `json:"oid" cbor:"oid"`           //三方的订单号
}

// 订单回调response
type paymentCallbackResp struct {
	AppId           string `json:"appId"`           //机构号
	CustId          string `json:"custId"`          //商户编号
	MerchantOrderId string `json:"merchantOrderId"` // 商户订单号
	Order           string `json:"order"`           // 平台订单号
	OrderStatus     string `json:"orderStatus"`     // 业务状态
	Amount          string `json:"amount"`          //金额
	Sign            string `json:"sign"`            // 签名
}

type TblRatelist struct {
	Id          int     `json:"id"`
	Ty          uint32  `json:"ty"`           //类型 0充值 1下发
	Rate        float64 `json:"rate"`         //手续费率 %
	Min         float64 `json:"min"`          //最少收取
	Max         float64 `json:"max"`          //最高收取
	UpdatedAt   uint32  `json:"updated_at"`   //修改时间
	UpdatedName string  `json:"updated_name"` //修改人
}

func WithdrawApply(fctx *fasthttp.RequestCtx, amount, bankId, payPassword, fid, flag string) (string, error) {

	uid := GetUidFromToken(fctx)
	if uid == "" {
		return "", errors.New(helper.AccessTokenExpires)
	}
	myUserHelp.LoadUserToRedis(uid)

	if myUserHelp.G_UserButton.GetWithdraw(uid) == myUserHelp.ButtonClose {
		return "", errors.New(helper.CfgErrWithdraw)
	}

	// 测试号
	if myUserHelp.GetMemberTester(uid) == 2 {
		withdrawAmount, _ := decimal.NewFromString(amount)

		_, err := BalanceIsEnough(uid, withdrawAmount)
		if err != nil {
			return "", err
		}

		withdrawId := helper.GenLongId() + "@" + meta.Program
		record := g.Record{
			"id":          withdrawId,
			"oid":         withdrawId,
			"uid":         uid,
			"parent_id":   myUserHelp.GetProxyParentId(uid),
			"fid":         fid,
			"amount":      withdrawAmount.Truncate(4).String(),
			"fee":         0.00,
			"state":       WithdrawSuccess,
			"withdraw_at": time.Now().Unix() + 1,
			"automatic":   0, //1:自动转账  0:人工确认
			"created_at":  fctx.Time().Unix(),
			"real_name":   myUserHelp.GetMemberRealName(uid),
			"pix_id":      "00000000000",
			"pix_account": "00000000000",
			"confirm_uid": 0,
			"flag":        flag,
		}

		query, _, _ := dialect.Insert("tbl_withdraw").Rows(record).ToSQL()
		_, errExec := GetMasterDBInstance().Exec(query)
		if errExec != nil {
			helper.SqlErrLog("[WithdrawApply:Exec]:insert sql: %s reason:%s", query, errExec.Error())
			return "", errors.New(helper.DBErr)
		}

		myUserHelp.MinusUserBalanceByDecimal(uid, withdrawAmount)
		myredis.ImmediateUpdateRole(uid)
		return withdrawId, nil
	}

	if myUserHelp.GetMemberState(uid) == 2 {
		return "", errors.New(helper.Blocked)
	}

	bank, err := BankcardFindOne(bankId, uid)
	if err != nil {
		return "", errors.New(helper.BankcardIDErr)
	}
	if bank.Uid != uid {
		return "", errors.New(helper.BankcardIDErr)
	}
	if bank.Flag == 3 && myConfig.IsBlackListMailSuffix(bank.PixAccount) {
		return "", errors.New(helper.EmailSuffixError)
	}

	// 卡号黑名单
	var pixCount int = 0
	SqlBlacklist := fmt.Sprintf("select count(1) from tbl_cfg_bankcard_blacklist where pix_id='%s'", bank.PixAccount)
	err = GetMasterDBInstance().Get(&pixCount, SqlBlacklist)
	if err != nil {
		helper.InfoLog("[withdrawLimit]SqlSelect:%s  reason:%s", SqlBlacklist, err.Error())
	}

	if pixCount > 0 {
		return "", errors.New(helper.CardInBlacklist)
	}

	PayPassword := myUserHelp.GetMemberPayPsw(uid)
	if PayPassword == "0" || PayPassword == "" {
		return "", errors.New(helper.SetWithdrawPwdFirst)
	}

	if payPassword == "" {
		return "", errors.New(helper.WithdrawPwdMismatch)
	}

	//pwd := fmt.Sprintf("%d", MurmurHash(payPassword, member.CreatedAt))
	//if pwd != member.PayPassword {
	if payPassword != PayPassword {
		return "", errors.New(helper.WithdrawPwdMismatch)
	}

	withdrawAmount, err := decimal.NewFromString(amount)
	if err != nil {
		return "", pushLog(err, helper.AmountErr)
	}
	withdrawMaxLimit := myConfig.GetGameCfgDecimal(myConfig.CfgWithdrawMaxLimit)
	withdrawMinLimit := myConfig.GetGameCfgDecimal(myConfig.CfgWithdrawMinLimit)
	fwithdrawAmount, _ := withdrawAmount.Float64()
	if (withdrawAmount.GreaterThan(withdrawMaxLimit) || withdrawAmount.LessThan(withdrawMinLimit)) || fwithdrawAmount <= 0.0 {
		return "", errors.New(helper.AmountOutRange)
	}

	withdrawId := helper.GenLongId() + "@" + meta.Program
	lk := fmt.Sprintf("w:%s", myUserHelp.GetMemberName(uid))
	err = WithLock(lk)
	if err != nil {
		return "", err
	}

	defer Unlock(lk)

	// 同时只能有一笔提款在处理中
	ex := g.Ex{
		"uid":   uid,
		"state": g.Op{"In": []int64{WithdrawReviewing, WithdrawDealing, WithdrawHangup}},
	}

	err = withdrawOrderExists(ex)
	if err != nil {
		return "", err
	}

	rate := myConfig.GetGameCfgDecimal(myConfig.CfgWithdrawalFees).Div(decimal.NewFromInt(100))
	feeReckon, _ := rate.Mul(withdrawAmount).Float64()
	fee := fmt.Sprintf("%.2f", feeReckon)
	feeAmount, _ := decimal.NewFromString(fee)

	// check balance
	_, err = BalanceIsEnough(uid, withdrawAmount)
	if err != nil {
		return "", err
	}

	EnableWithdrawMount := decimal.NewFromFloat(myUserHelp.GetEnableWithdrawMount(uid))
	if EnableWithdrawMount.Sub(withdrawAmount).IsNegative() {
		return "", errors.New(helper.LackOfEnableWithdrawBalance)
	}

	ParentId := myUserHelp.GetProxyParentId(uid)

	var automatic int = 0
	accuWithDraw := myUserHelp.GetTotalWithdraw(uid)
	accuDeposit := myUserHelp.GetTotalDeposit(uid)
	thisWithdrawAmount, _ := withdrawAmount.Float64()

	helper.InfoLog("withdrawapply:%s ---%0.2f----%0.2f", uid, (accuWithDraw + thisWithdrawAmount),
		(accuDeposit * myConfig.GetGameCfgFloat64(myConfig.CfgAutomaticWithdrawalMultipleLimit)))
	if myUserHelp.G_UserButton.GetAutoWithdraw(uid) == myUserHelp.ButtonOpen &&
		accuWithDraw+thisWithdrawAmount < accuDeposit*myConfig.GetGameCfgFloat64(myConfig.CfgAutomaticWithdrawalMultipleLimit) {
		automatic = 1
		helper.InfoLog("automatic  1111:%s ", uid)
	}

	if myUserHelp.G_UserButton.IsBloger(uid) == 1 &&
		myUserHelp.G_UserButton.GetAutoWithdraw(uid) == myUserHelp.ButtonOpen {
		var totalDeposit float64
		sqlSelect := fmt.Sprintf("SELECT deposit FROM tbl_proxy_accu WHERE UID=%s and level=1", uid)
		GetMasterDBInstance().Get(&totalDeposit, sqlSelect)
		if accuWithDraw+thisWithdrawAmount < totalDeposit*myConfig.GetGameCfgFloat64(myConfig.CfgBlogerAutomaticWithdrawalMultipleLimit) {
			automatic = 1
			helper.InfoLog("bloger  automatic 222:%s ", uid)
		}
	}

	//限额判断 超过限额不能自动出款
	SqlSelect := fmt.Sprintf("select IFNULL(sum(withdraw),0) from tbl_report_daily where business_id = 0 and operator_id=%s", myUserHelp.GetMemberOperatorId(uid))

	var totalWithdraw float64 = 0.0
	err = GetMasterDBInstance().Get(&totalWithdraw, SqlSelect)
	if err != nil {
		helper.InfoLog("[totalWithdraw]SqlSelect:%s  reason:%s", SqlSelect, err.Error())
	}

	var withdrawLimit float64 = 0.00
	SqlSelect = fmt.Sprintf("select auto_withdrawal_limit from tbl_operator_quota_manage where operator_id=%s", myUserHelp.GetMemberOperatorId(uid))
	err = GetMasterDBInstance().Get(&withdrawLimit, SqlSelect)
	if err != nil {
		helper.InfoLog("[withdrawLimit]SqlSelect:%s  reason:%s", SqlSelect, err.Error())
	}

	if totalWithdraw+thisWithdrawAmount > withdrawLimit {
		automatic = 0
		helper.InfoLog("automatic  222:%s ", uid)
	}

	//单次自动出款阀值
	var withdrawSingleLimit float64 = 0.00
	SqlSelect = fmt.Sprintf("select auto_withdrawal_single_limit from tbl_operator_quota_manage where operator_id=%s", myUserHelp.GetMemberOperatorId(uid))
	err = GetMasterDBInstance().Get(&withdrawSingleLimit, SqlSelect)
	if err != nil {
		helper.InfoLog("[withdrawLimit]SqlSelect:%s  reason:%s", SqlSelect, err.Error())
	}

	if thisWithdrawAmount > withdrawSingleLimit {
		automatic = 0
		helper.InfoLog("automatic  333:%s ", uid)
	}

	//遗留问题bank表中pix_account pix的KEY  pix_id 为身份证
	// tbl_withdraw表中这两个字段的意思相反  pix_id为key(即手机号 邮箱 CNPJ CPF)pix_account为玩家身份即CPF
	record := g.Record{
		"id":          withdrawId,
		"oid":         withdrawId,
		"uid":         uid,
		"parent_id":   ParentId,
		"fid":         fid,
		"amount":      withdrawAmount.Truncate(4).String(),
		"fee":         feeAmount,
		"state":       WithdrawReviewing,
		"automatic":   automatic, //1:自动转账  0:人工确认
		"created_at":  fctx.Time().Unix(),
		"real_name":   bank.RealName,
		"pix_id":      bank.PixAccount,
		"pix_account": bank.PixId,
		"confirm_uid": 0,
		"flag":        flag,
	}

	if myUserHelp.GetMemberState(uid) == 2 {
		record["state"] = WithdrawSuccess
		record["withdraw_at"] = time.Now().Unix() + 1
	}

	if err != nil {
		return "", pushLog(err, helper.DBErr)
	}

	query, _, _ := dialect.Insert("tbl_withdraw").Rows(record).ToSQL()

	//可提额度 临时额度 - 提现金额
	myUserHelp.AddUnlockAmount(uid, -fwithdrawAmount)
	if myUserHelp.GetUnlockAmount(uid) < 0 {
		myUserHelp.SetUnlockAmount(uid, 0)
	}

	myUserHelp.AddAgencyAmount(uid, -fwithdrawAmount)
	if myUserHelp.GetAgencyAmount(uid) < 0 {
		myUserHelp.SetAgencyAmount(uid, 0)
	}

	myUserHelp.AddBalanceTransactionRecord(uid, -fwithdrawAmount, helper.TransactionWithDraw, "0", withdrawId, 0.00, "", "", 0)
	myUserHelp.MinusUserBalanceByDecimal(uid, withdrawAmount)
	myredis.ImmediateUpdateRole(uid)

	//先改余额,再插入提现表
	//myredis.UpdateSqlFieldToRedis(query)
	_, errExec := GetMasterDBInstance().Exec(query)
	if errExec != nil {
		helper.SqlErrLog("[WithdrawApply:Exec]:insert sql: %s reason:%s", query, errExec.Error())
		return "", errors.New(helper.DBErr)
	}

	if automatic == 1 {
		headers := map[string]string{
			"Content-Type": "application/json;charset=utf-8",
		}

		requestURI := "http://127.0.0.1:8022/api/withdraw/toThird123qwe"
		args := map[string]string{"id": withdrawId}
		requestParams, _ := helper.JsonMarshal(args)
		statusCode, _, _ := myconn.HttpPostHeader(requestParams, requestURI, headers)
		if statusCode != fasthttp.StatusOK {
			helper.SqlSelectErrLog("toThird123qwe statusCode:%d", statusCode)
		}
	}

	return withdrawId, nil
}

func withdrawHandToAuto(fctx *fasthttp.RequestCtx, p TblPayFactory, uid, username, id string, amount float64, withdraw tblWithdraw) error {

	if len(p.Fid) == 0 {
		return errors.New(helper.CateNotExist)
	}

	//user, err := GetMemberBaseInfo(fctx, username)
	//if err != nil {
	//	return err
	//}

	as := strconv.FormatFloat(amount, 'f', -1, 64)
	// check amount range, continue the for loop if amount out of range
	_, ok := validator.CheckFloatScope(as, p.Fmin, p.Fmax)
	if !ok {
		return errors.New(helper.AmountOutRange)
	}
	//payment, ok := thirdFuncCb[p.Fid]
	//if !ok {
	//	return errors.New(helper.NoPayChannel)
	//}
	payment := &thirdEpay{}
	//data, err := payment.Withdraw(fctx, time.Now(), user.Uid, as, id, withdraw.PixAccount, withdraw.RealName, withdraw.PixId, withdraw.Flag, p)
	err := payment.Withdraw(as, id, withdraw.PixAccount, uid, withdraw.PixId, p)
	if err != nil {
		return err
	}
	err = withdrawAutoUpdate(id, WithdrawAutoPaying)
	return nil
}

func withdrawAutoUpdate(id string, state int) error {

	r := g.Record{"state": state, "automatic": "1"}
	query, _, _ := dialect.Update("tbl_withdraw").Set(r).Where(g.Ex{"id": id}).ToSQL()
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		return pushLog(err, helper.DBErr)
	}

	return err
}

func WithLock(id string) error {

	val := fmt.Sprintf("%s:%s", defaultRedisKeyPrefix, id)
	ok, err := meta.MerchantRedis.SetNX(ctx, val, "1", 120*time.Second).Result()
	if err != nil {
		return pushLog(err, helper.RedisErr)
	}
	if !ok {
		return errors.New(helper.RequestBusy)
	}

	return nil
}

// 检查订单是否存在
func withdrawOrderExists(ex g.Ex) error {

	var id string
	query, _, _ := dialect.From("tbl_withdraw").Select("id").Where(ex).ToSQL()
	err := meta.MerchantDB.Get(&id, query)

	if err != nil && err != sql.ErrNoRows {
		return pushLog(err, helper.DBErr)
	}

	if id != "" {
		return errors.New(helper.OrderProcess)
	}

	return nil
}

type withdrawTodayData struct {
	Total  sql.NullInt64 `db:"total"`
	Amount sql.NullInt64 `db:"amount"`
}

// 查今天提款次数和金额
func withdrawToday(uid string) (int64, int64, error) {

	var data withdrawTodayData
	ex := g.Ex{
		"uid":        uid,
		"state":      WithdrawSuccess,
		"created_at": helper.DayTST(0, loc).Unix(),
	}

	query, _, _ := dialect.From("tbl_withdraw").Select(g.COUNT("id").As("total"), g.SUM("amount").As("amount")).Where(ex).GroupBy(g.C("uid")).ToSQL()
	err := meta.MerchantDB.Get(&data, query)

	if err != nil && err != sql.ErrNoRows {
		return 0, 0, pushLog(err, helper.DBErr)
	}

	return data.Total.Int64, data.Amount.Int64, nil
}

func BankCardExist(ex g.Ex) bool {

	var id string
	t := dialect.From("tbl_member_bankcard")
	query, _, _ := t.Select("uid").Where(ex).Limit(1).ToSQL()
	err := meta.MerchantDB.Get(&id, query)
	if err == sql.ErrNoRows {
		return false
	}

	return true
}

// BalanceIsEnough 检查中心钱包余额是否充足
func BalanceIsEnough(uid string, amount decimal.Decimal) (decimal.Decimal, error) {
	brl := myUserHelp.GetBalanceByUid(uid, 2)
	if brl.Sub(amount).IsNegative() {
		return brl, errors.New(helper.LackOfBalance)
	}
	return brl, nil
}

func WithdrawConfig(fctx *fasthttp.RequestCtx) (WithdrawConfigData, error) {

	data := WithdrawConfigData{}
	uid := GetUidFromToken(fctx)
	if uid == "" {
		return data, errors.New(helper.AccessTokenExpires)
	}

	channels, err := ChannelList(fctx, 2)
	if err != nil || channels.T == 0 {
		return data, errors.New(helper.NoPayChannel)
	}
	data.Config = channels.D[0]
	bls, err := BankcardList(uid)
	if err != nil {
		return data, nil
	}
	//data.MemberBankList = bls.D
	data.MemberBankT = bls.T
	//memberVip, _ := getVip(member.Vip)
	amount, _ := UnfinishedAmount(uid, "1")
	pixId, _ := LastWithdrawPixId(uid)
	withdrawalFees := myConfig.GetGameCfgFloat64(myConfig.CfgWithdrawalFees)
	withdrawMaxLimit := myConfig.GetGameCfgFloat64(myConfig.CfgWithdrawMaxLimit)
	withdrawMinLimit := myConfig.GetGameCfgFloat64(myConfig.CfgWithdrawMinLimit)
	data.LockAmount = myUserHelp.GetBalanceFloat64ByUid(uid) - myUserHelp.GetEnableWithdrawMount(uid)
	if data.LockAmount < 0.00 {
		data.LockAmount = 0.0
	}
	data.PixId = pixId
	data.UnfinishedTotAmount = amount
	data.WithdrawalFees = withdrawalFees
	data.WithdrawMaxLimit = withdrawMaxLimit
	data.WithdrawMinLimit = withdrawMinLimit
	data.AgentWagedTimes = myConfig.GetGameCfgInt(myConfig.CfgAgentWagedTimes)
	if data.AgentWagedTimes <= 0 {
		data.AgentWagedTimes = 1
	}
	return data, nil
}

// 查找单条提款记录, 订单不存在返回错误: OrderNotExist
func withdrawFind(id string) (tblWithdraw, error) {

	w := tblWithdraw{}
	query, _, _ := dialect.From("tbl_withdraw").Select(colsWithdraw...).Where(g.Ex{"id": id}).Limit(1).ToSQL()
	err := meta.MerchantDB.Get(&w, query)
	if err == sql.ErrNoRows {
		return w, errors.New(helper.OrderNotExist)
	}

	if err != nil {
		return w, err
	}

	return w, nil
}

// 获取指定会员未完成总打码
func UnfinishedAmount(uid, state string) (float64, error) {

	sqlSelect := fmt.Sprintf("SELECT IFNULL(sum(NeedWageRequire),0) - IFNULL(sum(CurWageRequire),0) FROM tbl_member_wage_require WHERE uid=%s and status = 0", uid)
	var unFinishWage float64
	meta.MerchantDB.Get(&unFinishWage, sqlSelect)

	return unFinishWage, nil
}

// 获取玩家上一次提现账号
func LastWithdrawPixId(uid string) (string, error) {
	ex := g.Ex{}
	//ex["state"] = state
	ex["uid"] = uid
	var pixId string

	query, _, _ := dialect.From("tbl_withdraw").Select("pix_account").Where(ex).Order(g.C("withdraw_at").Desc()).Limit(1).ToSQL()
	err := meta.SlaveDB.Get(&pixId, query)
	if err != nil && err != sql.ErrNoRows {
		return pixId, errors.New(helper.DBErr)
	}
	return pixId, nil
}

func WithdrawList(fctx *fasthttp.RequestCtx, flag int) ([]UserWithdrawList, error) {

	var res []UserWithdrawList
	var list UserWithdrawList
	var withdraw []tblWithdraw
	uid := GetUidFromToken(fctx)
	if uid == "" {
		return res, errors.New(helper.AccessTokenExpires)
	}
	now := time.Now()
	var startTime, endTime int64
	switch flag {
	case 1:
		// Yesterday
		startTime = time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, loc).Unix()
		endTime = time.Date(now.Year(), now.Month(), now.Day()-1, 23, 59, 59, 0, loc).Unix()
	case 2:
		// Today
		startTime = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc).Unix()
		endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, loc).Unix()
	case 3:
		// Last 7 days
		startTime = time.Date(now.Year(), now.Month(), now.Day()-6, 0, 0, 0, 0, loc).Unix()
		endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, loc).Unix()
	case 4:
		// Last 15 days
		startTime = time.Date(now.Year(), now.Month(), now.Day()-14, 0, 0, 0, 0, loc).Unix()
		endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, loc).Unix()
	case 5:
		// Last 30 days
		startTime = time.Date(now.Year(), now.Month(), now.Day()-29, 0, 0, 0, 0, loc).Unix()
		endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, loc).Unix()
	default:
		// All time
		startTime = 0
		endTime = 0
	}

	ex := g.Ex{"uid": uid}
	//ex := g.Ex{"uid": uid, "state": []int{WithdrawReviewing, WithdrawReviewReject, WithdrawDealing, WithdrawSuccess, WithdrawFailed, WithdrawAutoPayFailed, WithdrawHangup, WithdrawDispatched, WithdrawAutoPaying}}
	if startTime != 0 && endTime != 0 {
		if startTime >= endTime {
			return res, errors.New(helper.QueryTimeRangeErr)
		}
		ex["created_at"] = g.Op{"between": exp.NewRangeVal(startTime, endTime)}
	}
	query, _, _ := dialect.From("tbl_withdraw").Select(colsWithdraw...).Where(ex).ToSQL()
	err := meta.SlaveDB.Select(&withdraw, query)
	if err == sql.ErrNoRows {
		return res, errors.New(helper.OrderNotExist)
	}

	if err != nil {
		return res, pushLog(err, helper.DBErr)
	}
	if len(withdraw) > 0 {
		for _, i := range withdraw {
			list.Id = i.ID
			list.CreatedAt = i.CreatedAt
			list.Amount = i.Amount
			list.Fee = i.Fee
			list.State = i.State
			list.Detail = ""
			res = append(res, list)
		}
	}

	return res, nil
}

type UserWithdrawList struct {
	Id        string  `json:"id" db:"id" cbor:"id"`
	CreatedAt int64   `json:"created_at" db:"created_at" cbor:"created_at"`
	Amount    float64 `json:"amount" db:"amount" cbor:"amount"`
	Fee       float64 `json:"fee" db:"fee" cbor:"fee"`
	State     int     `json:"state" db:"state" cbor:"state"`
	Detail    string  `json:"detail" db:"detail"`
}
